#if UNITY_EDITOR
using UnityEngine;
using UnityEngine.UIElements;

namespace GameDesigner
{
    internal class PanManipulator : MouseManipulator
    {
        private Vector2 m_Start;
        private bool m_Active;
        private VisualElement m_GraphUI;
        public Vector2 panSpeed { get; set; }

        public PanManipulator(VisualElement graphUI)
        {
            m_GraphUI = graphUI;
            m_Active = false;
            activators.Add(new ManipulatorActivationFilter
            {
                button = MouseButton.LeftMouse,
                modifiers = EventModifiers.Alt
            });
            activators.Add(new ManipulatorActivationFilter
            {
                button = MouseButton.MiddleMouse
            });
            activators.Add(new ManipulatorActivationFilter
            {
                button = MouseButton.MiddleMouse,
                modifiers = EventModifiers.Alt
            });
            activators.Add(new ManipulatorActivationFilter
            {
                button = MouseButton.RightMouse
            });
            panSpeed = new Vector2(1f, 1f);
        }

        protected override void RegisterCallbacksOnTarget()
        {
            target.RegisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
            target.RegisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
            target.RegisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
        }

        protected override void UnregisterCallbacksFromTarget()
        {
            target.UnregisterCallback<MouseDownEvent>(OnMouseDown, TrickleDown.TrickleDown);
            target.UnregisterCallback<MouseMoveEvent>(OnMouseMove, TrickleDown.TrickleDown);
            target.UnregisterCallback<MouseUpEvent>(OnMouseUp, TrickleDown.TrickleDown);
        }

        protected void OnMouseDown(MouseDownEvent e)
        {
            if (e.button == 1)
            {
                if (m_Active)
                {
                    ReleasePan(e);
                }
            }
            else if (CanStartManipulation(e))
            {
                m_Start = target.ChangeCoordinatesTo(m_GraphUI, e.localMousePosition);
                m_Active = true;
                target.CaptureMouse();
                e.StopPropagation();
            }
        }

        protected void OnMouseMove(MouseMoveEvent e)
        {
            if (e.button != 1 && m_Active)
            {
                Vector2 vector = target.ChangeCoordinatesTo(m_GraphUI, e.localMousePosition) - m_Start;
                Vector3 scale = m_GraphUI.transform.scale;
                m_GraphUI.transform.position += Vector3.Scale(vector, scale);
                e.StopPropagation();
            }
        }

        protected void OnMouseUp(MouseUpEvent e)
        {
            if (m_Active && CanStopManipulation(e))
            {
                ReleasePan(e);
            }
        }

        private void ReleasePan(EventBase e)
        {
            m_Active = false;
            target.ReleaseMouse();
            e.StopPropagation();
        }
    }
}
#endif